<?php
/**
 * 销售物料模型层
 *
 * @author kamisama.xia@gmail.com 
 * @version 0.1
 */

class material_mdl_sales_material extends dbeav_model{

    var $defaultOrder = array('sm_id',' DESC');

    static public $__shopLists = array();

    /**
     * 销售物料类型字段格式化
     * @param string $row 物料类型字段
     * @return string
     */
    function modifier_sales_material_type($row){
        if($row == '1'){
            return '普通';
        }elseif($row == '2'){
            return '促销';
        }elseif($row == '3'){
            return '赠品';
        }else{
            return '-';
        }
    }

    /**
     * 物料是否可见字段格式化
     * @param string $row 物料是否可见字段
     * @return string
     */
    function modifier_shop_id($row){

        if(empty(self::$__shopLists)){
            self::$__shopLists['_ALL_'] = '全部店铺';
            $shopObj = app::get('ome')->model('shop');
            $tmp_shops = $shopObj->getList('shop_id,name',array(),0,-1);
            foreach($tmp_shops as $k => $shop){
                self::$__shopLists[$shop['shop_id']] = $shop['name'];
            }
        }
        
        return isset(self::$__shopLists[$row]) ? self::$__shopLists[$row] : $row;
    }

    /**
     * 基础物料列表项扩展字段
     */
    function extra_cols(){
        return array(
            'column_retail_price' => array('label'=>'售价','width'=>'60','func_suffix'=>'retail_price'),
            'column_unit' => array('label'=>'包装单位','width'=>'60','func_suffix'=>'unit'),
        );
    }

    /**
     * 售价扩展字段格式化
     */
    function extra_retail_price($rows){
        return kernel::single('material_extracolumn_salesmaterial_retailprice')->process($rows);
    }

    /**
     * 包装单位扩展字段格式化
     */
    function extra_unit($rows){
        return kernel::single('material_extracolumn_salesmaterial_unit')->process($rows);
    }

    /**
    * 销售物料的过滤方法
    */
    public function _filter($filter,$tableAlias=null,$baseWhere=null){
        if (isset($filter['not_gift']) && $filter['not_gift'] == 1){
            $where .= '  AND sales_material_type IN (1,2)';
            unset($filter['not_gift']);
        }

        #对应店铺
        if(isset($filter['in_shop_id']) && !empty($filter['in_shop_id']))
        {
            if(!is_array($filter['in_shop_id']))
            {
                $filter['in_shop_id']    = explode(',', $filter['in_shop_id']);
            }
            foreach ($filter['in_shop_id'] as $key => $val)
            {
                if(empty($val)) unset($filter['in_shop_id'][$key]);
            }
            
            $where    .= " AND shop_id IN ('". implode("','", $filter['in_shop_id']) ."') ";
            unset($filter['in_shop_id']);
        }

        if($filter['slaes_material_type'] == 12){
            $where .= " AND sales_material_type IN (1,2)";
        }
        

        return parent::_filter($filter,$tableAlias,$baseWhere).$where;
    }

    /**
     * 导入模板的标题
     *
     * @param Null
     * @return Array
     */
    function exportTemplate($filter){
        foreach ($this->io_title($filter) as $v){
            $title[] = kernel::single('base_charset')->utf2local($v);
        }
        return $title;
    }

    /**
     * 导入导出的标题
     *
     * @param Null
     * @return Array
     */
    function io_title( $filter, $ioType='csv' ){
        switch( $filter )
        {
            case 'salesMaterial':
                $this->oSchema['csv'][$filter] = array(
                                                    '*:销售物料名称' => 'sales_material_name',
                                                    '*:销售物料编码' => 'sales_material_bn',
                                                    '*:物料类型' => 'sales_material_type',#普通、促销（暂时不支持）、 赠品 (只支持全部店铺)
                                                    '*:所属店铺' => 'shop_id',
                                                    
                                                    '*:物料成本价' => 'cost',
                                                    '*:物料售价' => 'retail_price',
                                                    '*:重量(g)' => 'weight',
                                                    '*:包装单位' => 'unit',
                                                    
                                                    '*:关联基础物料信息(促销类型多个以|竖线分隔)' => 'material_bn',#普通的填写基础物料编号(促销类型格式：物料编号1:数量1|物料编号2:数量2)
                                                );
                break;
        }
        
        $this->ioTitle[$ioType][$filter] = array_keys( $this->oSchema[$ioType][$filter] );
        return $this->ioTitle[$ioType][$filter];
    }

    /**
     * 准备导入的参数定义
     *
     * @param Null
     * @return Null
     */
    function prepared_import_csv(){
        $this->ioObj->cacheTime = time();
    }
    
    /**
     * 准备导入的数据主体内容部分检查和处理
     *
     * @param Array $data
     * @param Boolean $mark
     * @param String $tmpl
     * @param String $msg
     * @return Null
     */
    function prepared_import_csv_obj($data,$mark,$tmpl,&$msg = ''){
        return null;
    }
    
    /**
     * 准备导入的数据明细内容部分检查和处理
     *
     * @param Array $row
     * @param String $title
     * @param String $tmpl
     * @param Boolean $mark
     * @param Boolean $newObjFlag
     * @param String $msg
     * @return Null
     */
    function prepared_import_csv_row($row,$title,&$tmpl,&$mark,&$newObjFlag,&$msg)
    {
        $basicMaterialObj    = app::get('material')->model('basic_material');
        $salesMaterialObj    = app::get('material')->model('sales_material');
        $shopObj             = app::get('ome')->model('shop');
        $checkSalesLib    = kernel::single('material_sales_check');#数据检验有效性Lib类
        
        if (empty($row)){
            return true;
        }
        $mark = false;

        if( substr($row[0],0,1) == '*' ){
            $titleRs =  array_flip($row);
            $mark = 'title';
            
            #[防止重复]记录组织编码
            $this->material_bn_list      = array();
            $this->salesm_nums           = 1;
            
            return $titleRs;
        }else{
            $re = base_kvstore::instance('sales_material')->fetch('sales-'.$this->ioObj->cacheTime,$fileData);

            if( !$re ) $fileData = array();

            if(!$row[0]){
                $msg['error'] = "销售物料名称必须填写,销售物料编码：". $row[1];
                return false;
            }

            if(!$row[1]){
                $msg['error'] = "销售物料编码必须填写,销售物料编码：". $row[1];
                return false;
            }

            if(!$row[2]){
                $msg['error'] = "物料类型必须填写,销售物料编码：". $row[1];
                return false;
            }

            if(!$row[3]){
                $msg['error'] = "所属店铺必须填写,销售物料编码：". $row[1];
                return false;
            }

            /**
             * 赠品类型不需要填写物料售价
             * 
            if(!$row[5]){
                $msg['error'] = "物料售价必须填写,销售物料编码：". $row[1];
                return false;
            }
            **/

            if(isset($this->salesm_nums)){
                $this->salesm_nums ++;
                if($this->salesm_nums > 5000){
                    $msg['error'] = "导入的数量量过大，请减少到5000个以下！";
                    return false;
                }
            }
            
            #[防止重复]检查物料编号
            if(in_array($row[1], $this->material_bn_list))
            {
                $msg['error'] = 'Line '.$this->salesm_nums.'：物料编号【'. $row[1] .'】重复！';
                return false;
            }
            $this->material_bn_list[]    = $row[1];
            
            
            //销售物料类型(注：暂时只支持普通或赠品类型)
            if($row[2] == "普通")
            {
                $row[2] = 1;
            }
            elseif($row[2] =="促销")
            {
                $row[2] = 2;
            }
            elseif($row[2] =="赠品")
            {
                $row[2] = 3;
            }
            else
            {
                $msg['error'] = "销售物料类型填写的内容错误：".$row[2]."，请填写普通、促销、赠品";
                return false;
            }
            
            //所属店铺
            if($row[3] == '全部店铺')
            {
                $row[3]    = '_ALL_';
            }
            elseif(($row[2] == 3) && ($row[3] != '全部店铺'))
            {
                $msg['error']    = "赠品物料类型只能选择全部店铺,销售物料编码：". $row[1];
                return false;
            }
            elseif($row[3])
            {
                $shopRow    = $shopObj->dump(array('name'=>$row[3], 's_type'=>1), 'shop_id');
                if(empty($shopRow))
                {
                    $msg['error']    = "未找到填写的所属店铺,销售物料编码：". $row[1];
                    return false;
                }
                
                $row[3]    = $shopRow['shop_id'];
            }
            else
            {
                $msg['error']    = "所属店铺不能为空,销售物料编码：". $row[1];
                return false;
            }
            
            #数据检查
            if(($row[2] == 2))
            {
                #促销物料类型(至少关联一个基础物料)
                $tmp_at             = array();
                
                //关联基础物料
                if($row[8] == '')
                {
                    $msg['error']    = "促销类型销售物料请至少填写一个关联的基础物料编号,销售物料编码：". $row[1];
                    return false;
                }
                
                $tmp_salesMInfos    = explode('|', $row[8]);
                foreach($tmp_salesMInfos as $tmp_basicMInfo)
                {
                    $tmp_bnInfo    = explode(':', $tmp_basicMInfo);#格式：物料编号1:数量1|物料编号2:数量2
                    $tmp_binds[$tmp_bnInfo[0]]    = intval($tmp_bnInfo[1]);
                }
                unset($row[8]);
                
                #只有一种物料时，数量必须大于1
                foreach ($tmp_binds as $bn => $val)
                {
                    if((count($tmp_binds) == 1) && ($val < 2))
                    {
                        $msg['error']    = "销售物料编码：". $row[1] ."行中,只有一种基础物料：". $bn ."时数量必须大于1（例格式：物料编号1:数量2）";
                        return false;
                    }
                    
                    if ($val < 1)
                    {
                        $msg['error']    = "销售物料编码：". $row[1] ."行中,基础物料：". $bn ."的数量必须大于0（例格式：物料编号1:数量1|物料编号2:数量2）";
                        return false;
                    }
                }
                
                $row[8]    = $tmp_binds;
                foreach($row[8] as $bn => $val)
                {
                    $basicInfo    = $basicMaterialObj->getList('bm_id', array('material_bn'=>$bn), 0, 1);
                    if(!$basicInfo)
                    {
                        $msg['error']    = "销售物料编码：". $row[1] ."行中找不到关联的基础物料：". $bn ."（例格式：物料编号1:数量1|物料编号2:数量2）";
                        return false;
                    }else{
                        $tmp_at[$basicInfo[0]['bm_id']]    = $val;
                    }
                }
                
                #促销价格贡献占比
                $row[8]    = array();
                $tmp_pr    = array();
                
                $total     = 100;
                $count_basicM    = count($tmp_at);
                $count_i         = 1;
                
                foreach ($tmp_at as $key => $val)
                {
                    if($count_basicM == 1)
                    {
                        #只有一种物料时
                        $row[8][$key]['number']    = $val;
                        $row[8][$key]['rate']      = $total;
                        
                        #验证数据时使用
                        $tmp_pr[$key]    = $row[8][$key]['rate'];
                    }
                    else 
                    {
                        #多种物料时
                        $row[8][$key]['number']    = $val;
                        
                        $tmp_rate                  = intval($total / $count_basicM);
                        $row[8][$key]['rate']      = $tmp_rate;
                        
                        if($count_basicM == $count_i)
                        {
                            $row[8][$key]['rate']      = $total - ($tmp_rate * $count_basicM) + $tmp_rate;
                        }
                        
                        #验证数据时使用
                        $tmp_pr[$key]    = $row[8][$key]['rate'];
                        
                        $count_i++;
                    }
                }
            }
            else 
            {
                #普通、赠品物料类型(默认关联的基础物料可以为空)
                if($row[8])
                {
                    $basicInfo    = $basicMaterialObj->getList('bm_id', array('material_bn'=>$row[8]), 0, 1);
                    if(!$basicInfo)
                    {
                        $msg['error']    = "销售物料编码：". $row[1] ."行中找不到关联的基础物料：". $row[8];
                        return false;
                    }else{
                        $row[8]    = $basicInfo[0]['bm_id'];
                    }
                }
            }
            
            #销售物料扩展信息
            $row[4]    = floatval($row[4]);
            $row[5]    = floatval($row[5]);
            $row[6]    = intval($row[6]);
            $row[7]    = trim($row[7]);
            
            #赠品物料类型_成本价和售价必须等于0
            if($row[2] == 3)
            {
                if(($row[4] != 0) || ($row[5] != 0))
                {
                    $msg['error']    = "赠品物料类型成本价和售价必须等于0,销售物料编码：". $row[1];
                    return false;
                }
            }
            
            #拼接数据
            $sdf    = array(
                        'sales_material_name' => $row[0],
                        'sales_material_bn' => trim($row[1]),
                        'sales_material_type' => $row[2],
                        'shop_id' => $row[3],
                        'is_bind' => 2,
                        'bind_bm_id' => $row[8],
                        'at' => $tmp_at,
                        'pr' => $tmp_pr,
                        'sales_material_bn_crc32' => '',
                        'cost' => $row[4],
                        'retail_price' => $row[5],
                        'weight' => $row[6],
                        'unit' => $row[7],
            );
            
            #数据有效性检查
            $err_msg          = '';
            
            if(!$checkSalesLib->checkParams($sdf, $err_msg)){
                $msg['error']    = $err_msg .",物料编码:". $row[1];
                return false;
            }
            
            $fileData['salesm']['contents'][] = $sdf;
            base_kvstore::instance('sales_material')->store('sales-'.$this->ioObj->cacheTime,$fileData);
        }
        
        return null;
    }

    /**
     * 完成基础物料的导入
     *
     * @param Null
     * @return Null
     */
    function finish_import_csv(){
        base_kvstore::instance('sales_material')->fetch('sales-'.$this->ioObj->cacheTime,$data);
        base_kvstore::instance('sales_material')->store('sales-'.$this->ioObj->cacheTime,'');

        $oQueue = app::get('base')->model('queue');
        $aP = $data;
        $pSdf = array();

        $count = 0;
        $limit = 50;
        $page = 0;
        $orderSdfs = array();

        foreach ($aP['salesm']['contents'] as $k => $aPi){
            if($count < $limit){
                $count ++;
            }else{
                $count = 0;
                $page ++;
            }
            $pSdf[$page][] = $aPi;
        }

        foreach($pSdf as $v){
            $queueData = array(
                'queue_title'=>'销售物料导入',
                'start_time'=>time(),
                'params'=>array(
                    'sdfdata'=> $v,
                    'app' => 'material',
                    'mdl' => 'sales_material'
                ),
                'worker'=>'material_sales_material_to_import.run',
            );
            $oQueue->save($queueData);
        }
        $oQueue->flush();
        
        //记录日志
        $operationLogObj    = app::get('ome')->model('operation_log');
        $operationLogObj->write_log('sales_material_import@wms', 0, "批量导入销售物料,本次共导入". count($aP['salesm']['contents']) ."条记录!");
        
        return null;
    }
}
